﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xaml;
using System.Reflection;
using System.Windows.Data;
using MoneyBook.Windows.Markup;

namespace MoneyBook.Windows.Data {
    public class BindingHelper {

        public static UpdateSourceTriggerExtension GetUpdateSourceTrigger(DependencyObject obj) {
            return (UpdateSourceTriggerExtension)obj.GetValue(UpdateSourceTriggerProperty);
        }

        public static void SetUpdateSourceTrigger(DependencyObject obj, UpdateSourceTriggerExtension value) {
            obj.SetValue(UpdateSourceTriggerProperty, value);
        }

        public static readonly DependencyProperty UpdateSourceTriggerProperty =
            DependencyProperty.RegisterAttached("UpdateSourceTrigger", typeof(UpdateSourceTriggerExtension), typeof(BindingHelper), new PropertyMetadata(OnUpdateSourceTriggerChanged));

        private static void OnUpdateSourceTriggerChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
            
            //TODO: target の binding の変更やイベントの付け替えなど細かな制御が必要

            if (sender == null || !(sender is FrameworkElement)) {
                return;
            }
            UpdateSourceTriggerExtension extension = e.NewValue as UpdateSourceTriggerExtension;
            if (extension == null) {
                return;
            }
            FieldInfo field = sender.GetType().GetField(extension.TargetProperty + "Property", BindingFlags.Public | BindingFlags.Static);
            if (field == null) {
                return;
            }
            DependencyProperty dp = field.GetValue(sender) as DependencyProperty;
            if (dp == null) {
                return;
            }
            EventInfo ev = sender.GetType().GetEvent(extension.TargetEvent);
            if (ev == null) {
                return;
            }
            FrameworkElement target = sender as FrameworkElement;
            BindingExpression be = target.GetBindingExpression(dp);
            if (be == null) {
                return;
            }
            Handler eh = new Handler(be);
            ev.AddEventHandler(sender, Delegate.CreateDelegate(ev.EventHandlerType, eh, typeof(Handler).GetMethod("EventHandler")));
        }

        private class Handler {
            
            private BindingExpression be = null;

            public Handler(BindingExpression be){
                this.be = be;
            }

            public void EventHandler(object sender, EventArgs e) {
                if (be != null) {
                    be.UpdateSource();
                }
            }
        }
    }
}
